package zmee.sso;

import cn.hutool.http.HttpRequest;
import com.alipay.api.internal.util.json.ExceptionErrorListener;
import kd.bos.exception.KDBizException;
import kd.scm.common.util.MD5Util;
import org.apache.commons.lang.StringUtils;
import kd.bos.logging.Log;
import kd.bos.logging.LogFactory;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.KeyManagementException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * 派拉认证工具类
 * @author ncc
 *
 */
public class HttpRequestUtil {
	public static final String CODE = "code";
	public static final String REFRESH_TOKEN = "refresh_token";
	public static final String AUTHORIZATION_CODE = "authorization_code";
	public static final String APP_SECRET_KEY = "0a96a6397ceb79040059cfcd996615cf64ebcac5"; // 密钥，向IAM申请
	private static Log logger = LogFactory.getLog(HttpRequestUtil.class);
	
	public static String getRequestURL(HttpServletRequest request){
		String url = "";
		String scheme = request.getScheme();//协议
		int port = request.getServerPort();//端口
		String contextPath = request.getContextPath();
		String serverName = request.getServerName();

		StringBuffer sbUrl = new StringBuffer(scheme);
		sbUrl.append("://");
		sbUrl.append(serverName);
		if (80 != port && 443 != port) {
			sbUrl.append(":");
			sbUrl.append(port);
		}
		sbUrl.append(contextPath);
		url = sbUrl.toString();
		Map<String, String[]> parameterMap = request.getParameterMap();
		if(parameterMap!=null && parameterMap.size()>0){
			if(url.endsWith("/")){
				url = StringUtils.substring(url,0, url.length());
			}
			int i = 0;
			for(Map.Entry<String, String[]> entry : parameterMap.entrySet()){
				String flag = "?";
				if(i>0){
					flag = "&";
				}
				url += flag+entry.getKey()+"="+entry.getValue()[0];
				i++;
			}
		}
		return url;
	}

	static class miTM implements javax.net.ssl.TrustManager,
			javax.net.ssl.X509TrustManager {
		public java.security.cert.X509Certificate[] getAcceptedIssuers() {
			return null;
		}

		public boolean isServerTrusted(
				java.security.cert.X509Certificate[] certs) {
			return true;
		}

		public boolean isClientTrusted(
				java.security.cert.X509Certificate[] certs) {
			return true;
		}

		public void checkServerTrusted(
				java.security.cert.X509Certificate[] certs, String authType)
				throws java.security.cert.CertificateException {
			return;
		}

		public void checkClientTrusted(
				java.security.cert.X509Certificate[] certs, String authType)
				throws java.security.cert.CertificateException {
			return;
		}
	}
	
	

	/**
	 * 根据请求的URL是https还是http请求数据
	 * 
	 * @param sendUrl
	 * @param param
	 * @return
	 * @throws Exception
	 */
	public static String getResult(String sendUrl, String param)
			throws Exception {
		if (sendUrl.startsWith("https")) {
			logger.info("（HttpRequestUtil）getResult()- getResult()："+"into-getResultByHttps()");
			return getResultByHttps(sendUrl, param);
		}
		logger.info("（HttpRequestUtil）getResult()- getResult()："+"into-GetResultByHttp()");
		return getResultByHttp(sendUrl, param);
	}

	private static String getResultByHttps(String sendUrl, String param)
			throws NoSuchAlgorithmException, KeyManagementException,
			IOException {
		javax.net.ssl.TrustManager[] trustAllCerts = new javax.net.ssl.TrustManager[1];
		javax.net.ssl.TrustManager tm = new miTM();
		trustAllCerts[0] = tm;
		// javax.net.ssl.SSLContext sc =
		// javax.net.ssl.SSLContext.getInstance("SSL");
		javax.net.ssl.SSLContext sc = javax.net.ssl.SSLContext
				.getInstance("SSLv3");

		sc.init(null, trustAllCerts, null);
		HttpsURLConnection.setDefaultSSLSocketFactory(sc
				.getSocketFactory());

		HostnameVerifier ignoreHostnameVerifier = new HostnameVerifier() {
			public boolean verify(String arg0, SSLSession arg1) {
				return true;
			}
		};

		HttpsURLConnection.setDefaultHostnameVerifier(ignoreHostnameVerifier);

		OutputStream out = null;
		BufferedReader reader = null;
		String result = "";
		URL url = null;
		HttpsURLConnection conn = null;
		try {
			url = new URL(sendUrl);
			logger.info("（HttpRequestUtil）getResultByHttps()- url："+url);
			conn = (HttpsURLConnection) url.openConnection();
			conn.setRequestMethod("POST");
			conn.setRequestProperty("Content-type",
					"application/x-www-form-urlencoded");
			// 必须设置false，否则会自动redirect到重定向后的地址
			conn.setInstanceFollowRedirects(false);
			conn.setDoInput(true);
			conn.setDoOutput(true);
			conn.setRequestProperty("Charset", "UTF-8");
			conn.setRequestProperty("Connection", "Keep-Alive");
			conn.setConnectTimeout(15000);
			conn.setReadTimeout(15000);
			conn.connect();
			out = conn.getOutputStream();
			out.write(param.getBytes());
			InputStream input = conn.getInputStream();
			reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
			String line = "";
			StringBuffer sb = new StringBuffer();
			while ((line = reader.readLine()) != null) {
				sb.append(line);
			}
			result = sb.toString();
			logger.info("（HttpRequestUtil）getResultByHttps()- result："+result);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			logger.info("（HttpRequestUtil）getResultByHttps()- Exception e："+e);
		} finally {
			if (conn != null) {
				conn.disconnect();
			}
			if (out != null) {
				out.close();
			}
			if (reader != null) {
				reader.close();
			}
		}
		return result;
	}

	public static String getResultParam(String url,String param){
		String data = HttpRequest.get(url+param)
				.timeout(18000)
				.execute().body();
		return data;
	}

	private static String getResultByHttp(String sendUrl, String param)
			throws NoSuchAlgorithmException, KeyManagementException,
			IOException {

		HttpURLConnection conn = null;
		OutputStream out = null;
		BufferedReader reader = null;
		String result = "";
		try {

			URL url = new URL(sendUrl);
			logger.info("（HttpRequestUtil）getResultByHttp()- url："+url);
			conn = (HttpURLConnection) url.openConnection();
			conn.setRequestMethod("POST");
			conn.setDoInput(true);
			conn.setDoOutput(true);
			conn.setRequestProperty("Charset", "UTF-8");
			conn.setRequestProperty("Connection", "Keep-Alive");
			conn.setConnectTimeout(15000);
			conn.setReadTimeout(150000);
			conn.connect();
			out = conn.getOutputStream();
			out.write(param.getBytes());
			out.flush();
			out.close();
			InputStream input = conn.getInputStream();
			reader = new BufferedReader(new InputStreamReader(input, "UTF-8"));
			String line;
			StringBuffer sb = new StringBuffer();
			while ((line = reader.readLine()) != null) {
				sb.append(line);
			}
			result = sb.toString();
			logger.info("（HttpRequestUtil）getResultByHttp()- result："+result);
			
		} catch (Exception e) {
			e.printStackTrace();
			logger.info("（HttpRequestUtil）getResultByHttp()-Exception e："+e);
		} finally {
			if (reader != null) {
				reader.close();
			}
			out.close();
			conn.disconnect();
		}

		return result;
	}
	
	public static String getSign(Map<String, String> params,String secret)    
    {    
        String sign="";    
        StringBuilder sb = new StringBuilder();   
        //排序  
        Set<String> keyset=params.keySet();    
        TreeSet<String> sortSet=new TreeSet<String>();    
        sortSet.addAll(keyset);    
        Iterator<String> it=sortSet.iterator();   
        //加密字符串  
        while(it.hasNext())    
        {    
            String key=it.next();    
            String value=params.get(key);    
            sb.append(key).append(value);    
        }    
        sb.append("appkey").append(secret);    
        try {
			//sign= MD5Util.encode(sb.toString()).toUpperCase();
			sign = encode(sb.toString()).toUpperCase();
			//sign=  MD5Util.md5s(sb.toString()).toUpperCase();
        } catch (Exception e) {    
        }    
        return sign;    
    } 
	
	/**
	 * 组装获取用户api参数，含签名
	 * @param client_ID
	 * @param client_secret
	 * @param token
	 * @return
	 */
	public static String getUserParam(String client_ID, String client_secret,String token) {
		String nonce_str = radomString();
		String appkey=HttpRequestUtil.APP_SECRET_KEY;
		long timestamp= System.currentTimeMillis();
		
		Map<String, String> params = new HashMap<String, String>();
		
		params.put("client_id", client_ID);
		params.put("client_secret", client_secret);
		params.put("nonce_str", nonce_str);
		params.put("oauth_timestamp", String.valueOf(timestamp));
		if(token.contains("access_token=")){
			 int strStartIndex = token.indexOf("access_token=");
		     int strEndIndex = token.indexOf("&expires");
		     String access_token = token.substring(strStartIndex, strEndIndex).substring("access_token=".length());
		 	params.put("access_token", access_token);

		}else{
			params.put("access_token", token);
		}
		String sign = getSign(params, appkey+client_secret);
		StringBuffer tokenParam = new StringBuffer();
		for (String key : params.keySet()) {
			if(tokenParam.length()==0){
				tokenParam.append(key).append("=").append(params.get(key));
			}else{
				tokenParam.append("&").append(key).append("=").append(params.get(key));
			}
			
		 }
		tokenParam.append("&sign=").append(sign);
		return tokenParam.toString();
	}
	
	/**
	 * 组装检查心跳API参数含签名
	 * @param client_ID
	 * @param client_secret
	 * @return
	 */
	public static String getIAMServiceParam(String client_ID, String client_secret) {
		String nonce_str = radomString();
		String appkey=HttpRequestUtil.APP_SECRET_KEY;
		long timestamp= System.currentTimeMillis();
		
		Map<String, String> params = new HashMap<String, String>();
		
		params.put("client_id", client_ID);
		params.put("client_secret", client_secret);
		params.put("nonce_str", nonce_str);
		params.put("oauth_timestamp", String.valueOf(timestamp));
		String sign = getSign(params, appkey+client_secret);
		StringBuffer tokenParam = new StringBuffer();
		for (String key : params.keySet()) {
			if(tokenParam.length()==0){
				tokenParam.append(key).append("=").append(params.get(key));
			}else{
				tokenParam.append("&").append(key).append("=").append(params.get(key));
			}
			
		 }
		tokenParam.append("&sign=").append(sign);
		return tokenParam.toString();
	}
	
	private static String radomString(){
		  String result="";  
		        for(int i=0;i<10;i++){  
		            int intVal=(int)(Math.random()*26+97);  
		            result=result+(char)intVal;  
		        }  
		        return result;  
		 }

	/**
	 * 组装获取token api参数 含签名
	 * @param client_ID
	 * @param client_secret
	 * @param redirect_uri
	 * @param code
	 * @return
	 */
	public static String getAccessTokenParam(String client_ID, String client_secret, String redirect_uri, String code) {
		String nonce_str = radomString();
		String appkey=HttpRequestUtil.APP_SECRET_KEY;
		long timestamp= System.currentTimeMillis();
		
		Map<String, String> params = new HashMap<String, String>();
		
		params.put("client_id", client_ID);
		params.put("client_secret", client_secret);
		params.put("nonce_str", nonce_str);
		params.put("oauth_timestamp", String.valueOf(timestamp));
		params.put("code", code);
		params.put("redirect_uri",redirect_uri);
		params.put("grant_type", "authorization_code");
		String sign = getSign(params, appkey+client_secret);
		StringBuffer tokenParam = new StringBuffer();
		for (String key : params.keySet()) {
			if(tokenParam.length()==0){
				tokenParam.append(key).append("=").append(params.get(key));
			}else{
				tokenParam.append("&").append(key).append("=").append(params.get(key));
			}
			
		 }
		tokenParam.append("&sign=").append(sign);
		return tokenParam.toString();
	}

	/**
	 * @throws Exception
	 *
	 * @Title: requestPost @Description: TODO(这个方法作用是执行的方法) @param @param
	 *         参数是拼接的xml报文 @param @return 接口返回的xml报文 @return String 返回类型 @throws
	 */
	public static String requestPost( String xmlStr,String urlStr) throws Exception {
		DataOutputStream out = null;
		HttpURLConnection conn = null;
		BufferedReader reader = null;

//		String urlStr = "http://192.168.189.13:8081/FrontEnd/FrontEndServlet";


		try {
			URL url = new URL(urlStr); // 创建连接的URL对象
			conn = (HttpURLConnection) url.openConnection(); // 打开连接


			// 设置请求属
//			conn.setRequestProperty("Authorization", "Basic " + tokenStr);
			conn.setDoOutput(true);
			conn.setDoInput(true);
			conn.setUseCaches(false);
			conn.setConnectTimeout(60000);
			conn.setRequestMethod("POST");
			conn.setRequestProperty("Cache-Control", "no-cache");
			conn.setRequestProperty("Content-Type", "text/xml;charset=utf-8");
			conn.setRequestProperty("Accept-Charset", "utf-8");
			conn.setRequestProperty("contentType", "utf-8");
			conn.setRequestProperty("Connection", "Keep-Alive");
			conn.setRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 5.0; Windows NT; DigExt)");

			conn.connect(); // 进行连接
			out = new DataOutputStream(conn.getOutputStream());

			out.write(xmlStr.getBytes());
			out.flush();

			// 得到返回的响音
			reader = new BufferedReader(new InputStreamReader(conn.getInputStream(), "UTF-8"));

			// 构造一个空的StringBuffer对象，用于存储内存中的数据
			StringBuffer buf = new StringBuffer();
			String line = "";
			while ((line = reader.readLine()) != null)
				buf.append(new String(line.getBytes(), "UTF-8"));
			String retmsg = buf.toString();
			System.out.println(retmsg);
			logger.info("返回的报文：" + retmsg);
			return retmsg;

		} catch (Exception e) {
			e.printStackTrace();
			logger.info("SendToSap Error：" + e.getMessage());
			throw new Exception(e.getMessage());
		} finally {
			try {
				// 关闭连接
				if (conn != null)
					conn.disconnect();
				if (reader != null)
					reader.close();
				if (out != null)
					out.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
	private static MessageDigest _mdInst;
	private static char[] hexDigits = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};

	private static MessageDigest getMdInst() {
		if (_mdInst == null) {
			try {
				_mdInst = MessageDigest.getInstance("MD5");
			} catch (NoSuchAlgorithmException var1) {
				throw new KDBizException(var1.getMessage());
			}
		}

		return _mdInst;
	}
	public static final String encode(String s) {
		try {
			byte[] btInput = s.getBytes(StandardCharsets.UTF_8);
			MessageDigest mdInst = getMdInst();
			mdInst.update(btInput);
			byte[] md = mdInst.digest();
			int j = md.length;
			char[] str = new char[j * 2];
			int k = 0;

			for(int i = 0; i < j; ++i) {
				byte byte0 = md[i];
				str[k++] = hexDigits[byte0 >>> 4 & 15];
				str[k++] = hexDigits[byte0 & 15];
			}

			return new String(str);
		} catch (Exception var9) {
			logger.error(var9);
			return null;
		}
	}

}
